package gui.panels;

import data.BuildingType;
import data.logic.BuildingSquareTypeFactory;
import data.logic.BuildingSquareType;
import data.logic.Square;
import data.logic.VillageLogic;
import gui.MaiaWorld;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import maiaclient.interfaces.IBuildingListener;
import maiaclient.interfaces.IBuildingTypeListener;

/**
 *
 * @author groep 11
 * @date 2007-2008
 */
public class VillageMap extends JPanel implements MouseMotionListener, MouseListener, IBuildingListener, IBuildingTypeListener {

    private VillageLogic village;
    private Point temp = null;
    Point startpoint = new Point();
    MaiaWorld parent;

    public VillageMap(MaiaWorld parent) {

        setVillage(new VillageLogic());
        this.setBackground(Color.GRAY);
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        this.parent = parent;

        try {
            parent.getMaia().addBuildingTypeListener(this);
            parent.getMaia().requestBuildingTypes();
        } catch (IOException ex) {
            Logger.getLogger(VillageMap.class.getName()).log(Level.SEVERE, null, ex);
        }


    }

    public void loadBuildingInfo(BuildingSquareType buildingSqTp) {

        parent.getPnlBuildingInfo().updateBuildingInfo(buildingSqTp);
    }

    public void clearBuildingInfo() {
        parent.getPnlBuildingInfo().clearBuildingInfo();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Square[][] squares = village.getVillageSpots();
        int iSquareX = 0, jSquareY = 0;

        int squareWidth = (int) (this.getWidth() / village.getDimension().getWidth());
        int squareHeight = (int) (this.getHeight() / village.getDimension().getHeight());

        startpoint.x = (int) (this.getSize().getWidth() - squareWidth * (int) village.getDimension().getWidth()) / 2;
        startpoint.y = (int) (this.getSize().getHeight() - squareHeight * (int) village.getDimension().getHeight()) / 2;

        for (Square[] rij : squares) {
            for (Square v : rij) {
                if (v.isHighlighted()) {
                    g.setColor(Color.ORANGE);
                } else {
                    g.setColor(v.getSquareType().getColor());
                }
                if (v.getSquareType().getImageUrl() == null) {
                    g.fillRect(iSquareX * squareWidth + startpoint.x, jSquareY * squareHeight + startpoint.y, squareWidth, squareHeight);
                } else {
                    try {
                        BufferedImage dest = new BufferedImage(squareWidth, squareHeight, BufferedImage.TYPE_INT_RGB);
                        BufferedImage source = ImageIO.read(new File(v.getSquareType().getImageUrl()));
                        Graphics2D g2 = dest.createGraphics();

                        if (v.getSquareType() instanceof BuildingSquareType) {
                            g2.drawImage(source, 0, 0, squareWidth, squareHeight, null);
                        }
                        g2.dispose();


                        g.drawImage(dest, iSquareX * squareWidth + startpoint.x, jSquareY * squareHeight + startpoint.y, null);
                    } catch (IOException ex) {
                        Logger.getLogger(VillageMap.class.getName()).log(Level.SEVERE, null, ex);
                    }

                }
                jSquareY++;
            }
            jSquareY = 0;
            iSquareX++;
        }
    }

    public VillageLogic setVillage() {
        return village;
    }

    public void setVillage(VillageLogic village) {
        this.village = village;
    }

    public void destructBuilding(BuildingSquareType buildingSqtp) {
        village.destructBuilding(new Point(buildingSqtp.getBuilding().getLocationX(), buildingSqtp.getBuilding().getLocationY()));
        this.repaint();
    }

    public void updateBuildings(Vector<Square> buildings) {

        village.drawBuildings(buildings);
        this.repaint();
    }

    public void updateBuildingTypes(Vector<BuildingType> types) {

        BuildingSquareTypeFactory.getInstance().setBuildingTypes(types);

        parent.getMaia().addBuildingListener(this);
        try {
            parent.getMaia().requestBuildings();
        } catch (IOException ex) {
            Logger.getLogger(VillageMap.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void mouseDragged(MouseEvent e) {

    }

    public void mouseMoved(MouseEvent e) {

        int squareWidth = (int) (this.getWidth() / village.getDimension().getWidth());
        int squareHeight = (int) (this.getHeight() / village.getDimension().getHeight());

        int i = (int) Math.floor((e.getX() - startpoint.x) / squareWidth);
        int j = (int) Math.floor((e.getY() - startpoint.y) / squareHeight);

        // We can only do things if our cursor is over the WorldLogic
        if ((i < village.getDimension().getWidth()) && i >= 0 && j >= 0 &&
                (j < village.getDimension().getHeight()) && e.getX() > startpoint.x && e.getY() > startpoint.y) {

            //If we go over a "Building" cursor changes into a hand
            if (village.getVillageSpots()[i][j].getSquareType() instanceof BuildingSquareType) {
                setCursor(new Cursor(Cursor.HAND_CURSOR));
            } else {
                setCursor(new Cursor((Cursor.DEFAULT_CURSOR)));
            }

            if (parent.getPnlBuildingInfo().getSelectedBuildButton() != null) {
                if (temp != null) {
                    if (temp.x != i || temp.y != j) {
                        village.getVillageSpots()[temp.x][temp.y].setHighlighted(false);
                    }
                }
                if (village.getVillageSpots()[i][j].getSquareType().isBuildingPossible()) {
                    village.getVillageSpots()[i][j].setHighlighted(true);
                    temp = new Point(i, j);
                }
            }


        } else {
            //if we leave our world with mouse we have to delete highlight too
            if (temp != null) {
                village.getVillageSpots()[temp.x][temp.y].setHighlighted(false);
            }
        }
        this.repaint();
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
        int squareWidth = (int) (this.getWidth() / village.getDimension().getWidth());
        int squareHeight = (int) (this.getHeight() / village.getDimension().getHeight());

        int i = (int) Math.floor((e.getX() - startpoint.x) / squareWidth);
        int j = (int) Math.floor((e.getY() - startpoint.y) / squareHeight);

        // We can only do things if our cursor is over the WorldLogic
        if ((i < village.getDimension().getWidth()) && i >= 0 && j >= 0 &&
                (j < village.getDimension().getHeight()) && e.getX() > startpoint.x && e.getY() > startpoint.y) {

            // If we click on a Building, we need to set the Building Info
            if (village.getVillageSpots()[i][j].getSquareType() instanceof BuildingSquareType) {
                BuildingSquareType selectedBuilding = (BuildingSquareType) village.getVillageSpots()[i][j].getSquareType();
                loadBuildingInfo(selectedBuilding);
            } else {
                JToggleButton buildButton = parent.getPnlBuildingInfo().getSelectedBuildButton();
                if (buildButton != null) {
                    try {

                        BuildingSquareType newBuildingSqTp = BuildingSquareTypeFactory.getInstance().makeBuilding(buildButton.getActionCommand(), new Point(i, j));

                        int foodCost = -1;
                        String sFoodCost = "";
                        int woodCost = -1;
                        String sWoodCost = "";
                        int ironCost = -1;
                        String sIronCost = "";
                        int stoneCost = -1;
                        String sStoneCost = "";
                        int goldCost = -1;
                        String sGoldCost = "";

                        if (newBuildingSqTp.getBuilding().getFoodCost() != -1) {
                            foodCost = newBuildingSqTp.getBuilding().getFoodCost();
                        }
                        if (newBuildingSqTp.getBuilding().getWoodCost() != -1) {
                            woodCost = newBuildingSqTp.getBuilding().getWoodCost();
                        }
                        if (newBuildingSqTp.getBuilding().getIronCost() != -1) {
                            ironCost = newBuildingSqTp.getBuilding().getIronCost();
                        }
                        if (newBuildingSqTp.getBuilding().getStoneCost() != -1) {
                            stoneCost = newBuildingSqTp.getBuilding().getStoneCost();
                        }
                        if (newBuildingSqTp.getBuilding().getGoldCost() != -1) {
                            goldCost = newBuildingSqTp.getBuilding().getGoldCost();
                        }

                        if (parent.getPnlBuildingInfo().upgradeAble(newBuildingSqTp.getBuilding().getFoodCost(),
                                newBuildingSqTp.getBuilding().getWoodCost(), newBuildingSqTp.getBuilding().getIronCost(),
                                newBuildingSqTp.getBuilding().getStoneCost(), newBuildingSqTp.getBuilding().getGoldCost())) {
                            Square v = new Square(newBuildingSqTp);
                            v.setPosition(new Point(i, j));
                            village.drawNewBuilding(v);
                            parent.getMaia().addBuilding(newBuildingSqTp.getBuilding());
                            parent.getPnlBuildingInfo().updateResources(newBuildingSqTp.getBuilding().getFoodCost(),
                                    newBuildingSqTp.getBuilding().getWoodCost(), newBuildingSqTp.getBuilding().getIronCost(),
                                    newBuildingSqTp.getBuilding().getStoneCost(), newBuildingSqTp.getBuilding().getGoldCost());
                        
        
                        } else {
                            if (foodCost != -1) {
                                sFoodCost = foodCost + " Food ";
                            }
                            if (woodCost != -1) {
                                sWoodCost = woodCost + " Wood ";
                            }
                            if (stoneCost != -1) {
                                sStoneCost = stoneCost + " Stone ";
                            }
                            if (ironCost != -1) {
                                sIronCost = ironCost + " Iron ";
                            }
                            if (goldCost != -1) {
                                sGoldCost = goldCost + " Gold";
                            }

                            JOptionPane.showMessageDialog(parent, "You don't have enough resources to build this building." +
                                    " You need: " + sFoodCost + sWoodCost + sStoneCost + sIronCost + sGoldCost + ".");
                            village.getVillageSpots()[temp.x][temp.y].setHighlighted(false);
                            temp = null;
                            
                        }
                    } catch (IOException ex) {
                        Logger.getLogger(VillageMap.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                                clearBuildingInfo();
                

            }


            this.repaint();
        }

    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }
}
